package wh;

import wh.exceptions.BadIDFormat;
import wh.exceptions.IDCollisionException;
import wh.exceptions.MissingReferenceException;
import wh.iolists.CustomerList;
import wh.iolists.StorageDiskList;

public class Order implements Comparable<Order>
{
	private String orderID;
	private String customerID; // reference to the customer that placed the product
	private String productID; // reference to ordered product. 
							 // The specification states one order has one item, but this could be an Array of productIDs if several products per order 
	private int quantity;
	private static final String ORDER_IN_ID = "ord"; // Constant class value, avoiding duplication of this value for each object
	protected String customerName;
	
	protected String customerType;
	protected double totalCost; 
	private boolean isBusy = false;

    public Order(String orderID, String customerID, String productID, 
    		int quantity) throws BadIDFormat, IDCollisionException, MissingReferenceException
    {
        this.orderID = orderID.trim();
        this.customerID = customerID.trim(); // Originally validated by Customer class
        this.productID = productID.trim(); // Originally validated by StorageDisk class
        this.quantity = quantity;
        
        validateID();
		validateInput();
    }
    
    /**
     * 
     * @param orderID
     * @param customerID
     * @param productID
     * @param quantity
     * @param customerName
     * @throws BadIDFormat
     * @throws IDCollisionException
     * @throws MissingReferenceException
     */
    public Order(String orderID, String customerID, String productID, 
    		int quantity, String customerName)
    {
    	this.orderID = orderID.trim();
        this.customerID = customerID.trim(); // Originally validated by Customer class
        this.productID = productID.trim(); // Originally validated by StorageDisk class
        this.quantity = quantity;
        this.customerName = customerName;
    }
    
    /**
     * 
     * @throws BadIDFormat
     * @throws IDCollisionException
     */
    private void validateID() throws BadIDFormat, IDCollisionException {
    	
    	System.out.println("About to validate order");
    	if (orderID != null) 
		{
			char[] firstThreeData = { orderID.charAt(0), orderID.charAt(1), orderID.charAt(2) };
			String ordString = new String(firstThreeData);
			
			if (ordString.equals(ORDER_IN_ID)) // This should always be "ord".
			{
				// Progressing in the validation ..
				int stringSize = orderID.length();
				// From the size of the ID string (the end index position in it) I count back three positions to get to the
				// first character of the final three, and construct the string from there.
				char finalStartChar = orderID.charAt(stringSize-3);
				char[] finalSixData = { finalStartChar, orderID.charAt(stringSize-2), orderID.charAt(stringSize-1) };
				
				String endingString = new String(finalSixData);
				
				// Making sure that the digits of the unique integer has not spilled over to the last three positions of the ID 
				if (!Character.isDigit(finalStartChar)) {
					for (char c : finalSixData) // for-each is appropriate here
					{
						if (Character.isDigit(c))
							throw new BadIDFormat(orderID, endingString);
					}
				}
				// So far so good, checking if the ID is unique for Order
				StorageDiskList.CompareProductIDs(orderID); // This can throw exception
			}
			else
				throw new BadIDFormat(orderID, ordString);
			// At this point the order ID is valid.
			System.out.println("Order object valid");
		}
		else
			throw new IllegalArgumentException("It's null!");
    }
    
    /**
     * 
     * @throws MissingReferenceException
     */
    private void validateInput() throws MissingReferenceException {
    	
    	boolean hasCustomerID = CustomerList.findCustomerID(customerID);
    	if (hasCustomerID == false)
    	{
    		try {
				Manager.addUnProcessedOrder(productID);
			} catch (BadIDFormat e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IDCollisionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}  // Cannot process order since reference to customer is missing
    		throw new MissingReferenceException(customerID, "Customer");
    	}
    	
    	boolean hasProductID = StorageDiskList.hasProductID(productID);
    	if (hasProductID == false)
    	{
    		try {
				Manager.addUnProcessedOrder(productID);
			} catch (BadIDFormat e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IDCollisionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} // Cannot process order since reference to ordered product is missing
    		throw new MissingReferenceException(productID, "StorageDisk");
    	}
    }
    
    
    
    /**
     * @return The id.
     */    
    public String getOrderID() {
    	return orderID;
    }
    
    public String getCustomerID() {
    	return customerID;
    }
    
    public String getProductID() {
    	return productID;
    }
    
    public int getQuantity() {
    	return quantity;
    }
    
    public void setTotalCost(double total) {
    	
    	totalCost = total;
    }
    
    public void setCustomerType(String type) {
    	
    	customerType = type;
    }
    
    public double getTotalCost() {
    	return totalCost;
    }
    
    public String getCustomerType() {
    	return customerType;
    }
    
    // 
    public void setIsBusyProcessing(boolean truefalse) {
    	isBusy = truefalse;
    }
    
    public boolean isBusyProcessing() {
    	return isBusy;
    }
 
    /**
     * Test for content equality between two objects.
     * @param other The object to compare to this one.
     * @return true if the argument object has same id
     */
    public boolean equals(Object other)
    {
        if(other instanceof Order) {
            Order otherItem = (Order) other;
            return orderID.equals(otherItem.getOrderID());
        }
        else {
            return false;
        }
    }

    /**
     * Compare this object against another, for the purpose
     * of sorting. The fields are compared by id.
     * @param otherDetails The details to be compared against.
     * @return a negative integer if this id comes before the parameter's id,
     *         zero if they are equal and a positive integer if this
     *         comes after the other.
     */

    public int compareTo(Order otherDetails)
    {
        return orderID.compareTo(otherDetails.getOrderID());
    }    

    /**
     * @return A  string containing all details.
     */
    public String toString()
    {
        return orderID;
    }
    
    
}
